/*
biopp_iterators.h: Generic iterators.
    Copyright (C) 2009  Daniel Gutson, FuDePAN

    This file is part of Biopp.

    Biopp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Biopp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Biopp.  If not, see <http://www.gnu.org/licenses/>.

    NOTE: This file is in prototype stage, and is under active development.
*/

#ifndef BIOPP_ITERATORS_H
#define BIOPP_ITERATORS_H

namespace biopp
{

template <class T>
struct IteratorInterface
{
    virtual void restart() = 0;
    virtual bool end() const = 0;
    virtual void next() = 0;
    virtual void endOfUse() = 0;
    virtual const T& get() const = 0;
    virtual IteratorInterface<T>* clone() const = 0;
    virtual size_t count()
    {
        size_t ret(0);

        restart();

        while (!end())
        {
            ret++;
            next();
        }

        return ret;
    }
protected:
    virtual ~IteratorInterface() {}
};

template <class T>
class Iterator
{
public:
    Iterator() :
        iterInterface(NULL)
    {}

    Iterator(IteratorInterface<T>* i)
        : iterInterface(i)
    {}

    Iterator(const Iterator<T>& other)
    {
        iterInterface = other.iterInterface;
        other.iterInterface = NULL;
    }

    Iterator<T>& operator = (const Iterator<T>& other)
    {
        iterInterface = other.iterInterface;
        other.iterInterface = NULL;
        return *this;
    }

    void restart()
    {
        iterInterface->restart();
    }

    bool end() const
    {
        return iterInterface->end();
    }

    const T& operator *() const
    {
        return iterInterface->get();
    }

    const T* operator ->() const
    {
        return &iterInterface->get();
    }

    void next()
    {
        iterInterface->next();
    }

    void operator++()
    {
        next();
    }

    size_t count()
    {
        return iterInterface->count();
    }

    ~Iterator()
    {
        if (iterInterface != NULL)
            iterInterface->endOfUse();
    }

    Iterator<T> clone() const
    {
        return Iterator<T>(iterInterface->clone());
    }
private:
    mutable IteratorInterface<T>* iterInterface;
};

template <class T>
class ConstantIteratorImpl : public IteratorInterface<T>
{
    bool iterated;
    const T element;

    virtual void restart()
    {
        iterated = false;
    }

    virtual bool end() const
    {
        return iterated;
    }
    virtual void next()
    {
        iterated = true;
    }
    virtual void endOfUse()
    {
        delete this;
    }
    virtual const T& get() const
    {
        return element;
    }
    virtual IteratorInterface<T>* clone() const
    {
        return new ConstantIteratorImpl<T>(element);
    }
    virtual size_t count()
    {
        return 1;
    }
public:
    ConstantIteratorImpl(const T& element)
        : iterated(false), element(element)
    {}
};

template <class Alpha>
class AlphabetIterator 
{
    Alpha alpha;
public:

    AlphabetIterator()
    {
        restart();
    }

    AlphabetIterator(const Alpha& alpha)
      : alpha(alpha)
    {}

    void restart()
    {
        alpha.value = 0;
    }

    bool end() const
    {
        return (alpha.value == Alpha::Length);
    }

    const Alpha& operator *() const
    {
        return alpha;
    }

    const Alpha* operator ->() const
    {
        return &alpha;
    }

    void operator++()
    {
        alpha.value = (alpha.value + 1) % Alpha::Length;
    }

};

}
#endif

